package com.wh.message.redis.service.impl;

import com.wh.message.redis.service.RedisMessageService;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.UnsupportedEncodingException;
import java.util.Set;


/**
 * redis缓存
 * @author 谢泽鹏
 * @version V1.0
 * @Package com.wh.message.mongo.service.impl
 * @date 2014年10月8日 下午4:02:14
 * @Copyright 个人版权所有
 * @Company 贵州万华科技有限公司Copyright (c) 2018
 */
@Service(value = "redisMessageServiceImpl")
public class RedisMessageServiceImpl implements RedisMessageService {

	private static String redisCode = "utf-8";

	@Autowired
	private StringRedisTemplate redisTemplate;


	/**
	 * 删除keys
	 * @param keys 删除keys
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public long del(final String... keys) {
		return redisTemplate.execute(new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				long result = 0;
				for (int i = 0; i < keys.length; i++) {
					Boolean flag = connection.exists(keys[i].getBytes());
					if(flag){
						result = connection.del(keys[i].getBytes());
					}
				}
				return result;
			}
		});
	}

	/**
	 * 添加key和value (byte)
	 * @param key   添加key
	 * @param value 添加value
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void set(byte[] key, byte[] value) {
		this.set(key, value, 0L);
	}

	/**
	 * 添加key和value, 并且设置存活时间(byte)
	 * @param key      添加key
	 * @param value    添加value
	 * @param liveTime 存活时间liveTime(单位秒)
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void set(final byte[] key, final byte[] value, final long liveTime) {
		redisTemplate.execute(new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				connection.set(key, value);
				if (liveTime > 0) {
					connection.expire(key, liveTime);
				}
				return 1L;
			}
		});
	}

	/**
	 * 添加key和value
	 * @param key      添加key
	 * @param value    添加value
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void set(String key, String value) {
		this.set(key, value, 0L);
	}

	/**
	 * 添加key和value, 并且设置存活时间
	 * @param key      添加key
	 * @param value    添加value
	 * @param liveTime 存活时间liveTime(单位秒)
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void set(String key, String value, long liveTime) {
		this.set(key.getBytes(), value.getBytes(), liveTime);
	}

	/**
	 * 添加key和object
	 * @param key    添加key
	 * @param object 添加object
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void set(String key, Object object) {
		this.set(key, object, 0L);
	}

	/**
	 * 添加key和object, 并且设置存活时间
	 * @param key      主键key
	 * @param object   添加object
	 * @param liveTime 存活时间liveTime(单位秒)
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void set(String key, Object object, long liveTime) {
		this.set(key.getBytes(), JSONObject.fromObject(object).toString().getBytes(), liveTime);
	}

	/**
	 * 添加key和value (byte高并发)
	 * @param key      添加key
	 * @param value    添加value
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean setNX(final byte[] key, final byte[] value) {
		return this.setNX(key, value,0L);
	}

	/**
	 * 添加key和value, 并且设置存活时间(byte高并发)
	 * @param key      添加key
	 * @param value    添加value
	 * @param liveTime 存活时间liveTime(单位秒)
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean setNX(final byte[] key, final byte[] value, final long liveTime) {
		return redisTemplate.execute(new RedisCallback<Boolean>() {
			@Override
			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
				boolean flag = connection.setNX(key, value);
				if(flag) {
					if (liveTime > 0) {
						connection.expire(key, liveTime);
					}
				}
				return flag;
			}
		});
	}

	/**
	 * 获取key
	 * @param key  获取key
	 * @return
	 */
	@Override
	public String get(final String key) {
		return redisTemplate.execute(new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection connection)  throws DataAccessException {
				try {
					byte[] value= connection.get(key.getBytes());
					if(null != value){
						return new String(value, redisCode);
					}else{
						return null;
					}
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				return null;
			}
		});
	}

	/**
	 * 获取key对应T
	 * @param key   获取key
	 * @param cls   对应class
	 * @return
	 */
	@Override
	public Object getObject(final String key, final Class cls) {
		String str = redisTemplate.execute(new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection connection) throws DataAccessException {
				try {
					byte[] value = connection.get(key.getBytes());
					if(null != value){
						String str = new String(value, redisCode);
						return  str;
					}else{
						return null;
					}
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
				return null;
			}
		});
		if(null != str){
			return JSONObject.toBean(JSONObject.fromObject(str), cls);
		}else {
			return null;
		}
	}

	/**
	 * 通过正则获取配置所有key的Set集合
	 * @param pattern 正则表达式
	 * @return
	 */
	@Override
	public Set<?> keys(String pattern) {
		return redisTemplate.keys(pattern);
	}

	/**
	 * 检查key是否存在
	 * @param key  检查key
	 * @return
	 */
	@Override
	public boolean exists(final String key) {
		return redisTemplate.execute(new RedisCallback<Boolean>() {
			@Override
			public Boolean doInRedis(RedisConnection connection)  throws DataAccessException {
				return connection.exists(key.getBytes());
			}
		});
	}

	/**
	 * 清空redisDB
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public String clearDB() {
		return redisTemplate.execute(new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection connection)  throws DataAccessException {
				connection.flushDb();
				return "success";
			}
		});
	}

	/**
	 * 获取readisDB大小
	 */
	@Override
	public long dbSize() {
		return redisTemplate.execute(new RedisCallback<Long>() {
			@Override
			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.dbSize();
			}
		});
	}

	/**
	 * 判断链接是否成功
	 * @return PONG
	 */
	@Override
	public String ping() {
		return redisTemplate.execute(new RedisCallback<String>() {
			@Override
			public String doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.ping();
			}
		});
	}


}
